import math
from math import degrees, radians

import random
from random import randint
from random import randint as ri

import pyglet
from pyglet.gl import  *
from pyglet.window import key

import cocos
from cocos.actions import *
from cocos.layer import *
from cocos.scene import *
from cocos.director import director
from cocos.scenes.transitions import *
from cocos.sprite import Sprite

import Box2D as box2d


from res import Images
from turtle import *
from globalvars import *
from glprimitives import *

       
class BaseMap(Layer):
    "The arena~"
    def __init__(self, world, *args, **kwargs):
        "Init"
        super(BaseMap,self).__init__( *args, **kwargs)
        self.children_anchor_x = self.transform_anchor_x
        self.children_anchor_y = self.transform_anchor_y
        self.b2Offset = box2d.b2Vec2(self.children_anchor_x/RATIO,
                                    self.children_anchor_y/RATIO)
        self.world = world
        self.add(self.MapBG(self),z=1)
       
    def update(self,dt):
        pass
        
    def createWalls(self):
        pass
        
    def createPoints(self):
        pass
   
    class MapBG(Layer):
        "Game Background"
        def __init__(self,map):
            Layer.__init__(self)
            self.map = map
        def update(self,dt):
            pass
       

class Map1(BaseMap):
    "The basic arena"
    SCALE = 1.4
    RATIO = 30.0
    WIDTH = Images.cheap_brown_card.width*SCALE
    HEIGHT = Images.cheap_brown_card.height*SCALE
    B2WIDTH = WIDTH/RATIO
    B2HEIGHT = HEIGHT/RATIO
    SIZE = (WIDTH,HEIGHT)
    points = []
    def __init__(self, world, *args, **kwargs):
        super(Map1,self).__init__(world, *args, **kwargs)
        self.turtle = Turtle(self.world)
        self.turtle.body.position = (0/RATIO,0/RATIO)
        self.turtle.lastPos = box2d.b2Vec2(self.turtle.body.position.x, self.turtle.body.position.y)
        self.turtle.targetPt = self.turtle.body.position
        self.turtle.targetMarker.body.position = self.turtle.body.position
        self.world.addEntity(self.turtle,z=3)
        self.world.addEntity(self.turtle.targetMarker,z=3)
        self.world.addEntity(self.turtle.turtlePen,z=3)
        self.createWalls()
        self.createPoints()
        glClearColor(1.0, 1.0, 1.0, 1.0)
        
        
    def createWalls(self):
        "Walls"
        wallbodyDef = box2d.b2BodyDef()
        wallbodyDef.linearDamping = 0.6
        wallbodyDef.angularDamping = 0.6
       
        horiWallShapeDef = box2d.b2PolygonDef()
        horiWallShapeDef.SetAsBox(self.B2WIDTH/2, 5/RATIO, (0,0),0)
        horiWallShapeDef.friction = 0.5
        horiWallShapeDef.restitution = 0.6
        horiWallShapeDef.density = 0.3                                                                                                    
   
        hcoords = [  (box2d.b2Vec2(0/RATIO, self.B2HEIGHT/2), radians(0)),
                    (box2d.b2Vec2(0/RATIO, -self.B2HEIGHT/2), radians(0)) ]
        hverts = horiWallShapeDef.getVertices_b2Vec2()
        for pos, angle in hcoords:
            body = self.world.CreateBody(wallbodyDef)
            body.position = pos+ self.b2Offset
            body.angle = angle
            shape = body.CreateShape(horiWallShapeDef)
            
            lineVerts = [(v*RATIO).tuple() for v in hverts]
            wallLine = SingleQuad(*lineVerts)
            wallLine.position = ( (body.position-self.b2Offset)*RATIO).tuple() 
            self.add(wallLine)
       
        vertWallShapeDef = box2d.b2PolygonDef()
        vertWallShapeDef.SetAsBox(5/RATIO, self.B2HEIGHT/2, (0,0),0)
        vertWallShapeDef.friction = 0.5
        vertWallShapeDef.restitution = 0.6
        vertWallShapeDef.density = 0.3
       
        vcoords = [(box2d.b2Vec2(self.B2WIDTH/2, 0/RATIO), radians(0)),
                    (box2d.b2Vec2(-self.B2WIDTH/2, 0/RATIO), radians(0)) ]
        vverts = vertWallShapeDef.getVertices_b2Vec2()
       
        for pos, angle in vcoords:
            body = self.world.CreateBody(wallbodyDef)
            body.position = pos + self.b2Offset
            body.angle = angle
            shape = body.CreateShape(vertWallShapeDef)
            
            lineVerts = [(v*RATIO).tuple() for v in vverts]
            wallLine = SingleQuad(*lineVerts)
            wallLine.position = ( (body.position-self.b2Offset)*RATIO).tuple() 
            self.add(wallLine)
            
    def createPoints(self):
        coords =[ box2d.b2Vec2(0,0), 
                    box2d.b2Vec2(0,5),
                    box2d.b2Vec2(2,2),]
        for pos in coords:
            pt = Point(self.world, pos, coords.index(pos)+1, self.turtle)
            self.points.append(pt)
            self.world.addEntity(pt,z=1)
            
    def checkJoinedPoints(self,dt=0):
        for pt in self.points:
        
            pass
        
            
    def update(self,dt):
        pass
   
    class MapBG(BaseMap.MapBG):
        "Game Background"
        def __init__(self,map):
            BaseMap.MapBG.__init__(self,map)
            self.image= Sprite(Images.cheap_brown_card)
            self.image.scale = self.map.SCALE
            self.image.position = (0,0)#(pos[0]/2,pos[1]/2)
            self.add(self.image)
       
        def update(self,dt):
            pass
            
            

###--------------------------###       
#        
#    Point
#   - line drawn
#
###---------------------------### 

class Point(entity.Entity):
    def __init__(self, world, pos=box2d.b2Vec2(0,0),num=0,turtle=None,image=Images.point, *args, **kwargs):
        "Init and keys"
        entity.Entity.__init__(self, world, image, *args, **kwargs)
        self.turtle = turtle
        self.fsm = entity.FSM(self)
        self.color = (0,0,0)
        self.number = num
        self.label = Label(str(self.number),color=(0,0,0,255),
                           position=(30,0), font_size=self.width)
        self.add(self.label)

        "BodyDef"
        self.bodyDef = box2d.b2BodyDef()
        self.bodyDef.position = pos
        self.bodyDef.linearDamping = 0.5
        self.bodyDef.angularDamping = 0.5
        
        "Box ShapeDef"
        self.pointShapeDef = box2d.b2PolygonDef()
        self.pointShapeDef.SetAsBox(
                          self.width/RATIO/2.0, 
                         self.height/RATIO/2.0, 
                         (0,0), 0)
        self.pointShapeDef.density = 1.0
        self.pointShapeDef.friction = 0.3
        self.pointShapeDef.restitution = 0.6
        self.pointShapeDef.SetUserData(self)
        self.pointShapeDef.isSensor = True
        
        "Create the body and the shape(s)"
        self.body = self.world.CreateBody(self.bodyDef)
        self.pointShape = self.body.CreateShape(self.pointShapeDef)
        
        self.fsm.changeState(self.Unjoined(self))
        
        
    def isBumpedSomething(self):
        "Hit something"
        shape_pairs = [(p.shape1, p.shape2) for p in self.world.points]
        for shape1, shape2 in shape_pairs:
            entity1 = shape1.GetUserData()
            entity2 = shape2.GetUserData()
            if entity1 == self: return entity2
            elif entity2 == self:return entity1
        return None
    
    def update(self,dt):
        self.fsm.update(dt)
        
    class Unjoined(entity.State):
        def Execute(self,dt):
            bumped = self.ent.isBumpedSomething()
            if bumped == self.ent.turtle:
                pass
            
            self.ent.position = (self.ent.body.position * RATIO).tuple()
            self.ent.rotation = -(degrees(self.ent.body.angle))

    class Joined(entity.Entity):
        pass

